﻿/*
** Xin YUAN, 2023, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////

//for SIMD

#pragma pack(push, 16)

//Mat3x2<T>

template <typename T>
class Mat3x2
{
public:
	typedef T  ValueType;

public:
	union {
#pragma pack(push, 1)
		struct { T _11, _21, _12, _22, _13, _23; } v;
#pragma pack(pop)
		Mat<T, 3, 2> data;
	};

	Mat3x2() noexcept
	{
	}
	Mat3x2(const Mat3x2<T>& src) noexcept : v(src.v)
	{
	}
	Mat3x2(const T& _11, const T& _21, const T& _12, const T& _22, const T& _13, const T& _23) noexcept : v{_11, _21, _12, _22, _13, _23}
	{
	}
	Mat3x2(const Vec2<T>& v1, const Vec2<T>& v2, const Vec2<T>& v3) noexcept : v{v1.v._1, v1.v._2, v2.v._1, v2.v._2, v3.v._1, v3.v._2}
	{
	}

	Mat3x2<T>& operator=(const Mat3x2<T>& src) noexcept
	{
		v = src.v;
		return *this;
	}

	Mat3x2<T>& Set(const T& _11, const T& _21, const T& _12, const T& _22, const T& _13, const T& _23) noexcept
	{
		v._11 = _11;
		v._21 = _21;
		v._12 = _12;
		v._22 = _22;
		v._13 = _13;
		v._23 = _23;
		return *this;
	}

	Mat3x2<T>& operator+=(const T& t) noexcept
	{
		v._11 += t;
		v._21 += t;
		v._12 += t;
		v._22 += t;
		v._13 += t;
		v._23 += t;
		return *this;
	}
	Mat3x2<T>& operator+=(const Mat3x2<T>& m) noexcept
	{
		v._11 += m.v._11;
		v._21 += m.v._21;
		v._12 += m.v._12;
		v._22 += m.v._22;
		v._13 += m.v._13;
		v._23 += m.v._23;
		return *this;
	}
	Mat3x2<T>& operator-=(const T& t) noexcept
	{
		v._11 -= t;
		v._21 -= t;
		v._12 -= t;
		v._22 -= t;
		v._13 -= t;
		v._23 -= t;
		return *this;
	}
	Mat3x2<T>& operator-=(const Mat3x2<T>& m) noexcept
	{
		v._11 -= m.v._11;
		v._21 -= m.v._21;
		v._12 -= m.v._12;
		v._22 -= m.v._22;
		v._13 -= m.v._13;
		v._23 -= m.v._23;
		return *this;
	}

	Mat3x2<T>& operator*=(const T& t) noexcept
	{
		v._11 *= t;
		v._21 *= t;
		v._12 *= t;
		v._22 *= t;
		v._13 *= t;
		v._23 *= t;
		return *this;
	}
	Mat3x2<T>& operator/=(const T& t) noexcept
	{
		v._11 /= t;
		v._21 /= t;
		v._12 /= t;
		v._22 /= t;
		v._13 /= t;
		v._23 /= t;
		return *this;
	}

	Mat3x2<T> operator+(const T& t) const noexcept
	{
		return Mat3x2<T>(v._11 + t, v._21 + t, v._12 + t, v._22 + t, v._13 + t, v._23 + t);
	}
	Mat3x2<T> operator+(const Mat3x2<T>& m) const noexcept
	{
		return Mat3x2<T>(v._11 + m.v._11, v._21 + m.v._21, v._12 + m.v._12, v._22 + m.v._22, v._13 + m.v._13, v._23 + m.v._23);
	}
	Mat3x2<T> operator-(const T& t) const noexcept
	{
		return Mat3x2<T>(v._11 - t, v._21 - t, v._12 - t, v._22 - t, v._13 - t, v._23 - t);
	}
	Mat3x2<T> operator-(const Mat3x2<T>& m) const noexcept
	{
		return Mat3x2<T>(v._11 - m.v._11, v._21 - m.v._21, v._12 - m.v._12, v._22 - m.v._22, v._13 - m.v._13, v._23 - m.v._23);
	}

	Mat3x2<T> operator*(const T& t) const noexcept
	{
		return Mat3x2<T>(v._11 * t, v._21 * t, v._12 * t, v._22 * t, v._13 * t, v._23 * t);
	}
	Mat3x2<T> operator/(const T& t) const noexcept
	{
		return Mat3x2<T>(v._11 / t, v._21 / t, v._12 / t, v._22 / t, v._13 / t, v._23 / t);
	}

	Mat3x2<T> operator-() const noexcept
	{
		return Mat3x2<T>(-v._11, -v._21, -v._12, -v._22, -v._13, -v._23);
	}
};

template <typename T>
inline Mat3x2<T> operator+(const T& t, const Mat3x2<T>& m) noexcept
{
	return Mat3x2<T>(t + m.v._11, t + m.v._21, t + m.v._12, t + m.v._22, t + m.v._13, t + m.v._23);
}
template <typename T>
inline Mat3x2<T> operator-(const T& t, const Mat3x2<T>& m) noexcept
{
	return Mat3x2<T>(t - m.v._11, t - m.v._21, t - m.v._12, t - m.v._22, t - m.v._13, t - m.v._23);
}
template <typename T>
inline Mat3x2<T> operator*(const T& t, const Mat3x2<T>& m) noexcept
{
	return Mat3x2<T>(t * m.v._11, t * m.v._21, t * m.v._12, t * m.v._22, t * m.v._13, t * m.v._23);
}
template <typename T>
inline Mat3x2<T> operator/(const T& t, const Mat3x2<T>& m) noexcept
{
	return Mat3x2<T>(t / m.v._11, t / m.v._21, t / m.v._12, t / m.v._22, t / m.v._13, t / m.v._23);
}

//Mat3x3<T>

template <typename T>
class Mat3x3
{
public:
	typedef T  ValueType;

public:
	union {
#pragma pack(push, 1)
		struct { T _11, _21, _31, _12, _22, _32, _13, _23, _33; } v;
#pragma pack(pop)
		Mat<T, 3, 3> data;
	};

	Mat3x3() noexcept
	{
	}
	Mat3x3(const Mat3x3<T>& src) noexcept : v(src.v)
	{
	}
	Mat3x3(const T& _11, const T& _21, const T& _31, const T& _12, const T& _22, const T& _32, const T& _13, const T& _23, const T& _33) noexcept : v{_11, _21, _31, _12, _22, _32, _13, _23, _33}
	{
	}
	Mat3x3(const Vec3<T>& v1, const Vec3<T>& v2, const Vec3<T>& v3) noexcept : v{v1.v._1, v1.v._2, v1.v._3, v2.v._1, v2.v._2, v2.v._3, v3.v._1, v3.v._2, v3.v._3}
	{
	}

	Mat3x3<T>& operator=(const Mat3x3<T>& src) noexcept
	{
		v = src.v;
		return *this;
	}

	Mat3x3<T>& Set(const T& _11, const T& _21, const T& _31, const T& _12, const T& _22, const T& _32, const T& _13, const T& _23, const T& _33) noexcept
	{
		v._11 = _11;
		v._21 = _21;
		v._31 = _31;
		v._12 = _12;
		v._22 = _22;
		v._32 = _32;
		v._13 = _13;
		v._23 = _23;
		v._33 = _33;
		return *this;
	}

	Mat3x3<T>& operator+=(const T& t) noexcept
	{
		v._11 += t;
		v._21 += t;
		v._31 += t;
		v._12 += t;
		v._22 += t;
		v._32 += t;
		v._13 += t;
		v._23 += t;
		v._33 += t;
		return *this;
	}
	Mat3x3<T>& operator+=(const Mat3x3<T>& m) noexcept
	{
		v._11 += m.v._11;
		v._21 += m.v._21;
		v._31 += m.v._31;
		v._12 += m.v._12;
		v._22 += m.v._22;
		v._32 += m.v._32;
		v._13 += m.v._13;
		v._23 += m.v._23;
		v._33 += m.v._33;
		return *this;
	}
	Mat3x3<T>& operator-=(const T& t) noexcept
	{
		v._11 -= t;
		v._21 -= t;
		v._31 -= t;
		v._12 -= t;
		v._22 -= t;
		v._32 -= t;
		v._13 -= t;
		v._23 -= t;
		v._33 -= t;
		return *this;
	}
	Mat3x3<T>& operator-=(const Mat3x3<T>& m) noexcept
	{
		v._11 -= m.v._11;
		v._21 -= m.v._21;
		v._31 -= m.v._31;
		v._12 -= m.v._12;
		v._22 -= m.v._22;
		v._32 -= m.v._32;
		v._13 -= m.v._13;
		v._23 -= m.v._23;
		v._33 -= m.v._33;
		return *this;
	}

	Mat3x3<T>& operator*=(const T& t) noexcept
	{
		v._11 *= t;
		v._21 *= t;
		v._31 *= t;
		v._12 *= t;
		v._22 *= t;
		v._32 *= t;
		v._13 *= t;
		v._23 *= t;
		v._33 *= t;
		return *this;
	}
	Mat3x3<T>& operator/=(const T& t) noexcept
	{
		v._11 /= t;
		v._21 /= t;
		v._31 /= t;
		v._12 /= t;
		v._22 /= t;
		v._32 /= t;
		v._13 /= t;
		v._23 /= t;
		v._33 /= t;
		return *this;
	}

	Mat3x3<T> operator+(const T& t) const noexcept
	{
		return Mat3x3<T>(v._11 + t, v._21 + t, v._31 + t, v._12 + t, v._22 + t, v._32 + t, v._13 + t, v._23 + t, v._33 + t);
	}
	Mat3x3<T> operator+(const Mat3x3<T>& m) const noexcept
	{
		return Mat3x3<T>(v._11 + m.v._11, v._21 + m.v._21, v._31 + m.v._31, v._12 + m.v._12, v._22 + m.v._22, v._32 + m.v._32, v._13 + m.v._13, v._23 + m.v._23, v._33 + m.v._33);
	}
	Mat3x3<T> operator-(const T& t) const noexcept
	{
		return Mat3x3<T>(v._11 - t, v._21 - t, v._31 - t, v._12 - t, v._22 - t, v._32 - t, v._13 - t, v._23 - t, v._33 - t);
	}
	Mat3x3<T> operator-(const Mat3x3<T>& m) const noexcept
	{
		return Mat3x3<T>(v._11 - m.v._11, v._21 - m.v._21, v._31 - m.v._31, v._12 - m.v._12, v._22 - m.v._22, v._32 - m.v._32, v._13 - m.v._13, v._23 - m.v._23, v._33 - m.v._33);
	}

	Mat3x3<T> operator*(const T& t) const noexcept
	{
		return Mat3x3<T>(v._11 * t, v._21 * t, v._31 * t, v._12 * t, v._22 * t, v._32 * t, v._13 * t, v._23 * t, v._33 * t);
	}
	Mat3x3<T> operator/(const T& t) const noexcept
	{
		return Mat3x3<T>(v._11 / t, v._21 / t, v._31 / t, v._12 / t, v._22 / t, v._32 / t, v._13 / t, v._23 / t, v._33 / t);
	}

	Mat3x3<T> operator-() const noexcept
	{
		return Mat3x3<T>(-v._11, -v._21, -v._31, -v._12, -v._22, -v._32, -v._13, -v._23, -v._33);
	}
};

template <typename T>
inline Mat3x3<T> operator+(const T& t, const Mat3x3<T>& m) noexcept
{
	return Mat3x3<T>(t + m.v._11, t + m.v._21, t + m.v._31, t + m.v._12, t + m.v._22, t + m.v._32, t + m.v._13, t + m.v._23, t + m.v._33);
}
template <typename T>
inline Mat3x3<T> operator-(const T& t, const Mat3x3<T>& m) noexcept
{
	return Mat3x3<T>(t - m.v._11, t - m.v._21, t - m.v._31, t - m.v._12, t - m.v._22, t - m.v._32, t - m.v._13, t - m.v._23, t - m.v._33);
}
template <typename T>
inline Mat3x3<T> operator*(const T& t, const Mat3x3<T>& m) noexcept
{
	return Mat3x3<T>(t * m.v._11, t * m.v._21, t * m.v._31, t * m.v._12, t * m.v._22, t * m.v._32, t * m.v._13, t * m.v._23, t * m.v._33);
}
template <typename T>
inline Mat3x3<T> operator/(const T& t, const Mat3x3<T>& m) noexcept
{
	return Mat3x3<T>(t / m.v._11, t / m.v._21, t / m.v._31, t / m.v._12, t / m.v._22, t / m.v._32, t / m.v._13, t / m.v._23, t / m.v._33);
}

//Mat3x4<T>

template <typename T>
class Mat3x4
{
public:
	typedef T  ValueType;

public:
	union {
#pragma pack(push, 1)
		struct { T _11, _21, _31, _41, _12, _22, _32, _42, _13, _23, _33, _43; } v;
#pragma pack(pop)
		Mat<T, 3, 4> data;
	};

	Mat3x4() noexcept
	{
	}
	Mat3x4(const Mat3x4<T>& src) noexcept : v(src.v)
	{
	}
	Mat3x4(const T& _11, const T& _21, const T& _31, const T& _41, const T& _12, const T& _22, const T& _32, const T& _42, const T& _13, const T& _23, const T& _33, const T& _43) noexcept : v{_11, _21, _31, _41, _12, _22, _32, _42, _13, _23, _33, _43}
	{
	}
	Mat3x4(const Vec4<T>& v1, const Vec4<T>& v2, const Vec4<T>& v3) noexcept : v{v1.v._1, v1.v._2, v1.v._3, v1.v._4, v2.v._1, v2.v._2, v2.v._3, v2.v._4, v3.v._1, v3.v._2, v3.v._3, v3.v._4}
	{
	}

	Mat3x4<T>& operator=(const Mat3x4<T>& src) noexcept
	{
		v = src.v;
		return *this;
	}

	Mat3x4<T>& Set(const T& _11, const T& _21, const T& _31, const T& _41, const T& _12, const T& _22, const T& _32, const T& _42, const T& _13, const T& _23, const T& _33, const T& _43) noexcept
	{
		v._11 = _11;
		v._21 = _21;
		v._31 = _31;
		v._41 = _41;
		v._12 = _12;
		v._22 = _22;
		v._32 = _32;
		v._42 = _42;
		v._13 = _13;
		v._23 = _23;
		v._33 = _33;
		v._43 = _43;
		return *this;
	}

	Mat3x4<T>& operator+=(const T& t) noexcept
	{
		v._11 += t;
		v._21 += t;
		v._31 += t;
		v._41 += t;
		v._12 += t;
		v._22 += t;
		v._32 += t;
		v._42 += t;
		v._13 += t;
		v._23 += t;
		v._33 += t;
		v._43 += t;
		return *this;
	}
	Mat3x4<T>& operator+=(const Mat3x4<T>& m) noexcept
	{
		v._11 += m.v._11;
		v._21 += m.v._21;
		v._31 += m.v._31;
		v._41 += m.v._41;
		v._12 += m.v._12;
		v._22 += m.v._22;
		v._32 += m.v._32;
		v._42 += m.v._42;
		v._13 += m.v._13;
		v._23 += m.v._23;
		v._33 += m.v._33;
		v._43 += m.v._43;
		return *this;
	}
	Mat3x4<T>& operator-=(const T& t) noexcept
	{
		v._11 -= t;
		v._21 -= t;
		v._31 -= t;
		v._41 -= t;
		v._12 -= t;
		v._22 -= t;
		v._32 -= t;
		v._42 -= t;
		v._13 -= t;
		v._23 -= t;
		v._33 -= t;
		v._43 -= t;
		return *this;
	}
	Mat3x4<T>& operator-=(const Mat3x4<T>& m) noexcept
	{
		v._11 -= m.v._11;
		v._21 -= m.v._21;
		v._31 -= m.v._31;
		v._41 -= m.v._41;
		v._12 -= m.v._12;
		v._22 -= m.v._22;
		v._32 -= m.v._32;
		v._42 -= m.v._42;
		v._13 -= m.v._13;
		v._23 -= m.v._23;
		v._33 -= m.v._33;
		v._43 -= m.v._43;
		return *this;
	}

	Mat3x4<T>& operator*=(const T& t) noexcept
	{
		v._11 *= t;
		v._21 *= t;
		v._31 *= t;
		v._41 *= t;
		v._12 *= t;
		v._22 *= t;
		v._32 *= t;
		v._42 *= t;
		v._13 *= t;
		v._23 *= t;
		v._33 *= t;
		v._43 *= t;
		return *this;
	}
	Mat3x4<T>& operator/=(const T& t) noexcept
	{
		v._11 /= t;
		v._21 /= t;
		v._31 /= t;
		v._41 /= t;
		v._12 /= t;
		v._22 /= t;
		v._32 /= t;
		v._42 /= t;
		v._13 /= t;
		v._23 /= t;
		v._33 /= t;
		v._43 /= t;
		return *this;
	}

	Mat3x4<T> operator+(const T& t) const noexcept
	{
		return Mat3x4<T>(v._11 + t, v._21 + t, v._31 + t, v._41 + t, v._12 + t, v._22 + t, v._32 + t, v._42 + t, v._13 + t, v._23 + t, v._33 + t, v._43 + t);
	}
	Mat3x4<T> operator+(const Mat3x4<T>& m) const noexcept
	{
		return Mat3x4<T>(v._11 + m.v._11, v._21 + m.v._21, v._31 + m.v._31, v._41 + m.v._41, v._12 + m.v._12, v._22 + m.v._22, v._32 + m.v._32, v._42 + m.v._42, v._13 + m.v._13, v._23 + m.v._23, v._33 + m.v._33, v._43 + m.v._43);
	}
	Mat3x4<T> operator-(const T& t) const noexcept
	{
		return Mat3x4<T>(v._11 - t, v._21 - t, v._31 - t, v._41 - t, v._12 - t, v._22 - t, v._32 - t, v._42 - t, v._13 - t, v._23 - t, v._33 - t, v._43 - t);
	}
	Mat3x4<T> operator-(const Mat3x4<T>& m) const noexcept
	{
		return Mat3x4<T>(v._11 - m.v._11, v._21 - m.v._21, v._31 - m.v._31, v._41 - m.v._41, v._12 - m.v._12, v._22 - m.v._22, v._32 - m.v._32, v._42 - m.v._42, v._13 - m.v._13, v._23 - m.v._23, v._33 - m.v._33, v._43 - m.v._43);
	}

	Mat3x4<T> operator*(const T& t) const noexcept
	{
		return Mat3x4<T>(v._11 * t, v._21 * t, v._31 * t, v._41 * t, v._12 * t, v._22 * t, v._32 * t, v._42 * t, v._13 * t, v._23 * t, v._33 * t, v._43 * t);
	}
	Mat3x4<T> operator/(const T& t) const noexcept
	{
		return Mat3x4<T>(v._11 / t, v._21 / t, v._31 / t, v._41 / t, v._12 / t, v._22 / t, v._32 / t, v._42 / t, v._13 / t, v._23 / t, v._33 / t, v._43 / t);
	}

	Mat3x4<T> operator-() const noexcept
	{
		return Mat3x4<T>(-v._11, -v._21, -v._31, -v._41, -v._12, -v._22, -v._32, -v._42, -v._13, -v._23, -v._33, -v._43);
	}
};

template <typename T>
inline Mat3x4<T> operator+(const T& t, const Mat3x4<T>& m) noexcept
{
	return Mat3x4<T>(t + m.v._11, t + m.v._21, t + m.v._31, t + m.v._41, t + m.v._12, t + m.v._22, t + m.v._32, t + m.v._42, t + m.v._13, t + m.v._23, t + m.v._33, t + m.v._43);
}
template <typename T>
inline Mat3x4<T> operator-(const T& t, const Mat3x4<T>& m) noexcept
{
	return Mat3x4<T>(t - m.v._11, t - m.v._21, t - m.v._31, t - m.v._41, t - m.v._12, t - m.v._22, t - m.v._32, t - m.v._42, t - m.v._13, t - m.v._23, t - m.v._33, t - m.v._43);
}
template <typename T>
inline Mat3x4<T> operator*(const T& t, const Mat3x4<T>& m) noexcept
{
	return Mat3x4<T>(t * m.v._11, t * m.v._21, t * m.v._31, t * m.v._41, t * m.v._12, t * m.v._22, t * m.v._32, t * m.v._42, t * m.v._13, t * m.v._23, t * m.v._33, t * m.v._43);
}
template <typename T>
inline Mat3x4<T> operator/(const T& t, const Mat3x4<T>& m) noexcept
{
	return Mat3x4<T>(t / m.v._11, t / m.v._21, t / m.v._31, t / m.v._41, t / m.v._12, t / m.v._22, t / m.v._32, t / m.v._42, t / m.v._13, t / m.v._23, t / m.v._33, t / m.v._43);
}

#pragma pack(pop)

typedef Mat3x2<int32_t>   Mat3x2i;
typedef Mat3x2<uint32_t>  Mat3x2u;
typedef Mat3x2<float>     Mat3x2f;
typedef Mat3x2<double>    Mat3x2d;

typedef Mat3x3<int32_t>   Mat3x3i;
typedef Mat3x3<uint32_t>  Mat3x3u;
typedef Mat3x3<float>     Mat3x3f;
typedef Mat3x3<double>    Mat3x3d;

typedef Mat3x4<int32_t>   Mat3x4i;
typedef Mat3x4<uint32_t>  Mat3x4u;
typedef Mat3x4<float>     Mat3x4f;
typedef Mat3x4<double>    Mat3x4d;

////////////////////////////////////////////////////////////////////////////////
